﻿using System;
using System.Collections.Generic;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows;
using OnlineStore.View;
using OnlineStore.Model;
using System.Threading.Tasks;
using Microsoft.Playwright;
using Newtonsoft.Json.Linq;
using OnlineStore.Common;
using System.IO;
using OnlineStore.ViewModel;

namespace OnlineStore
{
    public class MianViewModel : NotifyBase
    {
        public MianViewModel()
        {
            this.TaskCommand = new CommandBase();
            this.TaskCommand.ExcuteAction = new Action<object>(this.TaskSetting);
            this.TaskCommand.CanExecuteFunc = new Func<object, bool>((o) => { return true; });

            this.SettingCommand = new CommandBase();
            this.SettingCommand.ExcuteAction = new Action<object>(this.Setting);
            this.SettingCommand.CanExecuteFunc = new Func<object, bool>((o) => { return true; });

            this.UserCommand = new CommandBase();
            this.UserCommand.ExcuteAction = new Action<object>(this.User);
            this.UserCommand.CanExecuteFunc = new Func<object, bool>((o) => { return true; });

            this.PwSettingCommand = new CommandBase();
            this.PwSettingCommand.ExcuteAction = new Action<object>(this.PwSetting);
            this.PwSettingCommand.CanExecuteFunc = new Func<object, bool>((o) => { return true; });

            this.StartCommand = new CommandBase();
            this.StartCommand.ExcuteAction = new Action<object>(this.Start);
            this.StartCommand.CanExecuteFunc = new Func<object, bool>((o) => { return true; });

            this.LoookAtLogCommand = new CommandBase();
            this.LoookAtLogCommand.ExcuteAction = new Action<object>(this.LoookAtLog);
            this.LoookAtLogCommand.CanExecuteFunc = new Func<object, bool>((o) => { return true; });
            SetInit();
        }

        /// <summary>
        /// 初始化设置
        /// </summary>
        private async void SetInit()
        {
            test = CheckTest();
            filePath = new FilePath(test);
            filePath.CheckFirst();

            MyMainModel = new MainModel();
            MyLogWindow = new LogWindow();
            MyLogViewModel = new LogViewModel();

            MyStatus = new ExecuteStatus();   
            orderTask = OrderTask.GetOrderTask();
            orderTask.Print = Print;
            myPlaywright = await Playwright.CreateAsync();
        }

        /// <summary>
        /// 获取或设置 ExecuteStatus（执行状态 ） 对象
        /// </summary>
        ExecuteStatus MyStatus { get; set; }

        /// <summary>
        /// 获取或设置 LogWindow 对象
        /// </summary>
        public LogWindow MyLogWindow { get; set; }

        /// <summary>
        /// 获取或设置 LogViewModel 对象
        /// </summary>
        public LogViewModel MyLogViewModel { get; set; }

        /// <summary>
        /// 获取或设置 MainModel 对象
        /// </summary>
        public MainModel MyMainModel { get; set; }

        OrderTask orderTask;

        DataController dataController;

        IPlaywright myPlaywright;

        private bool test;

        FilePath filePath;

        private string notepad = "notepad.exe";

        public IPlaywright MyPlaywright { get; set; }

        /// <summary>
        /// 详细日志窗口的文本输出框对象
        /// </summary>
        private TextBlock logTextBlock;
        public TextBlock LogTextBlock
        {
            get { return logTextBlock; }
            set { logTextBlock = value; }
        }

        /// <summary>
        /// 输出详细任务进度
        /// </summary>
        /// <param name="before">当前进度</param>
        /// <param name="maxLength">总进度值</param>
        public async void ProgressPrint(int before,int maxLength)
        {
            await Task.Run(() =>
            {
                double progress = ((before * 0.1) / maxLength) * 10;
                MyMainModel.TaskInfo = $"上传进度: {progress * 100} %";
                MyMainModel.Progress = progress;
            });
        }
        
        /// <summary>
        /// 输出任务日志内容
        /// </summary>
        /// <param name="text"></param>
        public async void Print(string text)
        {
            await Task.Run(() =>
            {
                MyMainModel.TaskInfo = text;
            });
        }

        /// <summary>
        /// 输出详细日志内容
        /// </summary>
        /// <param name="text"></param>
        public async void DetailedPrint(string text)
        {
            await Task.Run(() =>
            {
                MyLogWindow.logModel.DetailedInfo = text;
            });
        }

        
        /// <summary>
        /// 任务设置按钮事件
        /// </summary>
        public CommandBase TaskCommand { get; set; }
        private async void TaskSetting(object parameter)
        {
            await Task.Run(() =>
            {
                MyMainModel.TaskInfo = "---------执行任务设置---------";
                System.Diagnostics.Process.Start(notepad, filePath.tasksConfig);
            });
        }

        /// <summary>
        /// 发布设置按钮事件
        /// </summary>
        public CommandBase SettingCommand { get; set; }
        private async void Setting(object parameter)
        {
            await Task.Run(() =>
            {
                MyMainModel.TaskInfo = "---------执行发布设置---------";
                System.Diagnostics.Process.Start(notepad, filePath.settingConfig);
            });
        }

        /// <summary>
        /// 驱动设置按钮事件
        /// </summary>
        public CommandBase PwSettingCommand { get; set; }
        private async void PwSetting(object parameter)
        {
            await Task.Run(() =>
            {
                MyMainModel.TaskInfo = "---------执行驱动设置---------";
                System.Diagnostics.Process.Start(notepad, filePath.pwSttingConfig);
            });
        }

        /// <summary>
        /// 用户设置按钮事件
        /// </summary>
        public CommandBase UserCommand { get; set; }
        private async void User(object parameter)
        {
            await Task.Run(() =>
            {
                MyMainModel.TaskInfo = "---------执行用户设置---------";
                System.Diagnostics.Process.Start(notepad, filePath.userConfig);
            });
        }


        /// <summary>
        /// 更改执行状态
        /// </summary>
        private void IsStop()
        {
            if (MyStatus.Status) 
            {
                if (!MyStatus.IsOk)
                {
                    string contents =
                        "!!!!!!!!!!!!!!!!!!!!!!!! 正在停止任务，请稍等 !!!!!!!!!!!!!!!!!!!!!!!!";
                    Print(contents);
                    return;
                }
                MyStatus.Status = false;
                MyStatus.IsOk = false;
                MyMainModel.Content = "停止执行";
            }
            else 
            {
                
                MyStatus.Status = true;
                if (!MyStatus.IsOk)
                {
                    return;
                }
                MyMainModel.Content = "开始执行";
            }
        }

        /// <summary>
        /// 开始任务按钮事件
        /// </summary>
        public CommandBase StartCommand { get; set; }
        /// <summary>
        /// 开始执行任务
        /// </summary>
        private async void Start(object parameter)
        {
            IsStop();
            if (MyStatus.Status)
            {
                Print("=================== 正在停止任务，请稍等 ===================");
                return;
            }
            dataController = new DataController(filePath);
            dataController.Print = Print;
            bool isOk = dataController.CheckAllConfig();
            if (!isOk) { return; }

            int cycle = Int32.Parse(dataController.SettingConfig["循环次数"].ToString());
            int closedTime = Int32.Parse(dataController.SettingConfig["关机计时"].ToString());
            int isTip = Int32.Parse(dataController.SettingConfig["完成提示"].ToString());
            int tipCount = Int32.Parse(dataController.SettingConfig["提示次数"].ToString());

            IBrowser browser = null;

            string content =
                     "----------------------------开始执行任务---------------------------- \n" +
                    $"标题文件目录：{$"{dataController.SettingConfig["标题文件目录"]}"} \n" +
                    $"网店发布间隔：{$"{dataController.SettingConfig["网店发布间隔"]}"} \n" +
                    $"发布延迟：{$"{dataController.SettingConfig["发布延迟"]}"} \n" +
                    $"保存登录：{$"{dataController.SettingConfig["保存登录"]}"} \n" +
                    $"是否循环：{MyMainModel.IsCycle} \n" +
                    $"循环次数：{cycle} \n" +
                    $"结束关机：{MyMainModel.IsClose} \n" +
                    $"关机计时：{closedTime} \n" +
                    $"完成提示：{isTip} \n" +
                    $"提示次数：{tipCount} \n" +
                    $"----------------------------------------------------------------------";

            MyMainModel.CleanInfo();
            Print(content);

            try
            {
                browser = await GetBrowser(myPlaywright, dataController.PwSettingConfig);
            }
            catch (Exception)
            {
                // 如果没有安装浏览器驱动，则需要运行这行代码
                //Program.Main(new string[] { "install" });  //安装所有驱动
                //Program.Main(new string[] { "install firefox" });  //只安装火狐浏览器驱动
                MessageBox.Show("请先安装浏览器驱动！！！");
                return;
            }


            if (!MyMainModel.IsCheck & MyMainModel.IsCycle)
            {
                if (cycle <= 0 ) { cycle = 1; }
                for (int i = 0; i < cycle; i++)
                {
                    if (MyStatus.Status) { break; }

                    Print($"---------------------------【第 {i + 1} 轮循环开始】---------------------------");
                    await DoingTask(browser);
                    Print($"---------------------------【第 {i + 1} 轮循环结束】---------------------------");
                }
            }
            else
            {
                await DoingTask(browser);
            }

            Print("关闭浏览器 browser");
            await browser.CloseAsync();

            if (MyStatus.Status)
            {
                MyMainModel.IsClose = false;
                Print("=================== 任务已经停止执行 ===================");
            }

            MyStatus.Status = true;
            MyStatus.IsOk = true;
            MyMainModel.Content = "开始执行";

            if (isTip != 0) Music.PlaySystemMyMusic(tipCount);

            if (!MyMainModel.IsCheck & MyMainModel.IsClose)
            {
                Print("正在执行关机，请稍等！");
                ShutdownHelper shutdown = new ShutdownHelper();
                shutdown.Closed(closedTime);
            }
            else
            {
                MyMainModel.IsCheck = false;
            }
        }

        /// <summary>
        /// 查看LOG
        /// </summary>
        public CommandBase LoookAtLogCommand { get; set; }
        /// <summary>
        /// 查看详细日志
        /// </summary>
        private void LoookAtLog(object parameter)
        {
            if (MyLogWindow != null)
            {
                MyLogWindow.Show();
            }
            else
            {
                MyLogWindow = new LogWindow();
                MyLogWindow.Show();
            }
        }

        /// <summary>
        /// 创建浏览器对象,返回浏览器对象
        /// </summary>
        async Task<IBrowser> GetBrowser(IPlaywright playwright, JObject pwSettingConfig)
        {
            bool headless;  // 是否隐藏浏览器
            int slowMo; // 每个步骤的执行时间
            float timeout;  // 超时时间
            IBrowser browser;

            if (MyMainModel.IsCheck)
            {
                headless = false;
                string contents =
                    "----------------------------------------------------------------------\n" +
                    "                               执行稳定测试\n" +
                    "----------------------------------------------------------------------";
                Print(contents);
            }
            else
            {
                headless = MyMainModel.IsBack;
            }

            if (!float.TryParse(pwSettingConfig["Timeout"].ToString(), out timeout))
            {
                timeout = 10;
            }

            if (!Int32.TryParse(pwSettingConfig["SlowMo"].ToString(), out slowMo))
            {
                slowMo = 800;
            }

            Print("选择 浏览器驱动");
            switch (pwSettingConfig["browser"].ToString())
            {
                case "Firefox":
                    Print("选择 Firefox");
                    browser = await playwright.Firefox.LaunchAsync(new BrowserTypeLaunchOptions
                    {
                        Headless = headless,
                        SlowMo = slowMo, //设置浏览器每步操作的等待时间
                        Timeout = timeout * 1000  //设置超时时间
                    });
                    break;
                //case "Chromium":
                //    Print("选择 Chromium");
                //    browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions
                //    {
                //        Headless = headless,
                //        SlowMo = slowMo,
                //        Timeout = timeout * 1000
                //    });
                //    break;
                //case "Webkit":
                //    Print("选择 Webkit");
                //    browser = await playwright.Webkit.LaunchAsync(new BrowserTypeLaunchOptions
                //    {
                //        Headless = headless,
                //        SlowMo = slowMo,
                //        Timeout = timeout * 1000
                //    });
                //    break;
                default:
                    Print("选择 Firefox");
                    browser = await playwright.Firefox.LaunchAsync(new BrowserTypeLaunchOptions
                    {
                        Headless = headless,
                        SlowMo = slowMo,
                        Timeout = timeout * 1000
                    });
                    break;
            }

            string browserInfo =
                $"browser：{pwSettingConfig["browser"]} \n" +
                $"headless：{headless} \n" +
                $"slowMo：{slowMo} \n" +
                $"timeout：{timeout}";
            Print(browserInfo);

            return browser;
        }

        /// <summary>
        /// 执行任务
        /// </summary>
        /// <param name="browser"></param>
        /// <returns></returns>
        async Task DoingTask(IBrowser browser)
        {
            try
            {
                List<PlayerTask> playerTasks = dataController.GetPlayerTask(MyMainModel.IsCheck);
                Player player = null;
                foreach (PlayerTask playerTask in playerTasks)
                {
                    switch (playerTask.Type)
                    {
                        case "淘宝":
                            player = new TaoBaoPlayer(playerTask, MyStatus);
                            break;
                        //case "天猫":
                        //    player = new TianMaoPlayer(playerTask, myStatus);
                        //    break;
                        //case "拼多多":
                        //    player = new PinDuoDuoPlayer(playerTask, myStatus);
                        //     break;
                        default:
                            player = new TaoBaoPlayer(playerTask, MyStatus);
                            break;
                    }
                    player.DetailedAction = DetailedPrint;
                    player.ProgressAction = ProgressPrint;
                    orderTask.Add(player);
                }
                await orderTask.Run(browser);
                playerTasks.Clear();
            }
            catch (Exception e)
            {
                Print(e.Message);
            }
        }

        /// <summary>
        /// 获取父控件的指定类型子控件
        /// </summary>
        public List<T> FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
        {
            try
            {
                List<T> list = new List<T>();
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                    if (child is T)
                    {
                        list.Add((T)child);
                        List<T> childOfChildren = FindVisualChild<T>(child);
                        if (childOfChildren != null)
                        {
                            list.AddRange(childOfChildren);
                        }
                    }
                    else
                    {
                        List<T> childOfChildren = FindVisualChild<T>(child);
                        if (childOfChildren != null)
                        {
                            list.AddRange(childOfChildren);
                        }
                    }
                }
                return list;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
                return null;
            }
        }

        /// <summary>
        /// 判断是否为测试模式
        /// </summary>
        /// <returns></returns>
        private bool CheckTest()
        {
            string path = Directory.GetCurrentDirectory() + @"\test.txt";
            if (File.Exists(path)) return true;
            return false;
        }
    }
}
